VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "clsCIRPriceProcess"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
Option Base 0

    '***********************************************************************************************************
    '
    '   This class is a Cox-Ingersoll_Ross interest-rate process.
    '   It is used to mimic interest rates that must be positive.
    '
    '       dr = Alpha * (B - r) * dT + sqrt(r) * Sigma * dW
    '
    '       dT is the incremental time
    '       Alpha is the annualized mean reversion speed in percent (the auto-regressive coefficient),
    '       B is the Expectation (mean-value) of r,
    '       Sigma is the volatility in annualized percent (standard deviation of the Weiner process)
    '       dW is a normally distributed random variable with zero mean and
    '           standard deviation one (the Weiner process)
    '
    '   The integration of dr will contain a non-central Chi-Squared distribution, because the interest
    '   rates are not symmetrically distributed around B:
    '
    '       r(t) = Sigma^2 * (1 - exp(-Alpha * t))/ 4 * Alpha * ChiSq(d, L)
    '
    '       where t is the time increment in fractions of a year, and
    '       d = 4 * Alpha * B / Sigma^2
    '       L = 4 & Alpha * r(0) / (Sigma^2 * (exp(Alpha * t) - 1))
    '
    '   Because it is impossible (AFAIK) to apply marginal correlations to the non-central Chi-Squared distribution
    '   we use numerical integration of the dr form to compute r(t):
    '
    '       r(t) = r(t-1) + dr
    '
    '   The process only moves forward in time, it only remembers its last position.  We need to keep deltaT
    '   small enough so that r(t) never goes negative
    '
    '   The Normally-distributed process variables are generated externally.
    '
    '   Also:
    '       E[r(t)] = r(0) * exp(-Alpha * t) +  B * (1 - exp(-Alpha * t))
    '       Var[r(t)] = r(0) * Sigma^2 / AlphaX * exp(-Alpha * t) * (1 - exp(-AlphaX * t)) +
    '                       B * Sigma^2 / (2 * AlphaX) * (1 - exp(-AlphaX * t))^2
    '
    '***********************************************************************************************************

Private mInitialized As Boolean
Private mr As Double
Private mInitialValue As Double
Private mMean As Double
Private mSigma As Double
Private mAlpha As Double
Private mVar As Double
Private mSqrDeltaT As Double
Private mDeltaT As Double
Private CumTime As Double

Public Property Let InitialValue(Val As Double)

    mInitialValue = Val
    mr = Val
    
End Property

Public Property Let Mean(Val As Double)

    mMean = Val
    mInitialized = False
    
End Property

Public Property Let Sigma(Val As Double)

    mSigma = Val
    
End Property

Public Property Let Alpha(Val As Double)

    mAlpha = Val
    mInitialized = False
    
End Property

Public Property Let DeltaTime(Val As Double)

    mDeltaT = Val
    mInitialized = False
    
End Property

Public Property Get Interest() As Double
    
    Interest = mr
    
End Property

Public Function Expectation(Time As Double)
    
    Expectation = mInitialValue * Exp(-mAlpha * Time) + mMean * (1 - Exp(-mAlpha * Time))
    
End Function

Public Function Var(Time As Double)

    Var = mInitialValue * mSigma ^ 2 / mAlpha * (Exp(-mAlpha * Time) - Exp(-2# * mAlpha * Time)) + _
            mMean * mSigma ^ 2 / (2 * mAlpha) * (1 - Exp(-mAlpha * Time)) ^ 2
            
End Function


Public Sub Step(dW As Double)

    If (Not mInitialized) Then Reset
    
    mr = mr + mAlpha * (mMean - mr) * mDeltaT + Sqr(mr) * mVar * dW
    'If (mr + deltar < 0) Then
    '    MsgBox "Error in clsCIRPriceProcess Numerical Integration", vbCritical, "clsCIRPriceProcess"
    'End If
    If (mr < 0) Then mr = 0
    CumTime = CumTime + 1#
    
End Sub

Public Sub Reset()

    mSqrDeltaT = Sqr(mDeltaT)
    mVar = mSigma * mSqrDeltaT
    mr = mInitialValue
    CumTime = 0
    mInitialized = True
    
End Sub
Private Sub Class_Initialize()

    mr = 0#
    mDeltaT = 0#
    mMean = 0#
    mSigma = 0#
    mAlpha = 0#
    CumTime = 0#
    mInitialValue = 0#
        
End Sub




